using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Lzfy_His_Service.Services;
using System.Diagnostics;
using Microsoft.Data.SqlClient;
using Oracle.ManagedDataAccess.Client;
using System.Data;
using Dapper;
using Microsoft.Extensions.Configuration;

namespace Lzfy_His_Service.Controllers
{
    /// <summary>
    /// 健康检查控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class HealthController : ControllerBase
    {
        private readonly ILogger<HealthController> _logger;
        private readonly ApplicationHealthCheckService _healthCheckService;
        private readonly IConfiguration _configuration;

        public HealthController(
            ILogger<HealthController> logger,
            ApplicationHealthCheckService healthCheckService,
            IConfiguration configuration)
        {
            _logger = logger;
            _healthCheckService = healthCheckService;
            _configuration = configuration;
        }

        /// <summary>
        /// 基础健康检查端点
        /// </summary>
        [HttpGet]
        [AllowAnonymous]
        public IActionResult Get()
        {
            try
            {
                var (isHealthy, lastCheckTime, metrics) = _healthCheckService.GetHealthStatus();
                
                if (isHealthy)
                {
                    return Ok(new
                    {
                        status = "healthy",
                        timestamp = DateTime.Now,
                        lastCheckTime = lastCheckTime,
                        uptime = GetUptime()
                    });
                }
                else
                {
                    return StatusCode(503, new
                    {
                        status = "unhealthy",
                        timestamp = DateTime.Now,
                        lastCheckTime = lastCheckTime,
                        uptime = GetUptime()
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "健康检查失败");
                return StatusCode(503, new
                {
                    status = "error",
                    message = "健康检查服务异常",
                    timestamp = DateTime.Now
                });
            }
        }

        /// <summary>
        /// 详细健康检查端点
        /// </summary>
        [HttpGet("detailed")]
        [Authorize(Roles = "Admin,SystemAdmin")]
        public IActionResult GetDetailed()
        {
            try
            {
                var (isHealthy, lastCheckTime, metrics) = _healthCheckService.GetHealthStatus();

                var result = new
                {
                    overall = new
                    {
                        status = isHealthy ? "healthy" : "unhealthy",
                        timestamp = DateTime.Now,
                        uptime = GetUptime()
                    },
                    applicationHealth = new
                    {
                        isHealthy = isHealthy,
                        lastCheckTime = lastCheckTime,
                        metrics = metrics
                    },
                    system = new
                    {
                        processId = Environment.ProcessId,
                        machineName = Environment.MachineName,
                        osVersion = Environment.OSVersion.ToString(),
                        dotNetVersion = Environment.Version.ToString(),
                        workingSet = Environment.WorkingSet,
                        gcTotalMemory = GC.GetTotalMemory(false)
                    }
                };

                if (isHealthy)
                {
                    return Ok(result);
                }
                else
                {
                    return StatusCode(503, result);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "详细健康检查失败");
                return StatusCode(500, new
                {
                    status = "error",
                    message = "健康检查服务异常",
                    error = ex.Message,
                    timestamp = DateTime.Now
                });
            }
        }

        /// <summary>
        /// 就绪检查端点（用于容器编排）
        /// </summary>
        [HttpGet("ready")]
        [AllowAnonymous]
        public IActionResult Ready()
        {
            return Ok(new
            {
                status = "ready",
                timestamp = DateTime.Now
            });
        }

        /// <summary>
        /// 存活检查端点（用于容器编排）
        /// </summary>
        [HttpGet("live")]
        [AllowAnonymous]
        public IActionResult Live()
        {
            try
            {
                // 简单的存活检查，只要进程还在运行就返回成功
                return Ok(new
                {
                    status = "alive",
                    timestamp = DateTime.Now,
                    processId = Environment.ProcessId
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "存活检查失败");
                return StatusCode(500, new
                {
                    status = "error",
                    message = "存活检查异常",
                    timestamp = DateTime.Now
                });
            }
        }

        /// <summary>
        /// 手动触发垃圾回收
        /// </summary>
        [HttpPost("gc")]
        [Authorize(Roles = "Admin,SystemAdmin")]
        public IActionResult TriggerGarbageCollection()
        {
            try
            {
                var beforeMemory = GC.GetTotalMemory(false);
                
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                
                var afterMemory = GC.GetTotalMemory(false);
                var freedMemory = beforeMemory - afterMemory;
                
                _logger.LogInformation("手动触发垃圾回收，释放内存: {FreedMemory} bytes", freedMemory);
                
                return Ok(new
                {
                    message = "垃圾回收完成",
                    beforeMemory = beforeMemory,
                    afterMemory = afterMemory,
                    freedMemory = freedMemory,
                    timestamp = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "手动垃圾回收失败");
                return StatusCode(500, new
                {
                    message = "垃圾回收失败",
                    error = ex.Message,
                    timestamp = DateTime.Now
                });
            }
        }

        /// <summary>
        /// 获取应用运行时间
        /// </summary>
        private TimeSpan GetUptime()
        {
            using var process = Process.GetCurrentProcess();
            return DateTime.Now - process.StartTime;
        }

        /// <summary>
        /// 获取Oracle连接池详细状态
        /// </summary>
        [HttpGet("oracle-pool-status")]
        [Authorize(Roles = "Admin,SystemAdmin")]
        public IActionResult GetOraclePoolStatus()
        {
            try
            {
                var poolStats = ResilientOracleConnectionFactory.GetPoolStats();
                
                // 获取Oracle连接池统计信息
                var oracleStats = new Dictionary<string, object>();
                try
                {
                    // 使用简单的连接测试来评估连接池状态
                    using var connection = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hisdb-scan)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=hisdb)));User Id=his_read;Password=his_read;Connection Timeout=30;Min Pool Size=5;Max Pool Size=50;Pooling=true;");
                    var startTime = DateTime.Now;
                    connection.Open();
                    var openTime = (DateTime.Now - startTime).TotalMilliseconds;
                    
                    var command = connection.CreateCommand();
                    command.CommandText = "SELECT 1 FROM DUAL";
                    command.CommandTimeout = 5;
                    var result = command.ExecuteScalar();
                    
                    oracleStats = new Dictionary<string, object>
                    {
                        ["ConnectionOpenTimeMs"] = openTime,
                        ["QueryResult"] = result,
                        ["IsHealthy"] = true,
                        ["ConnectionState"] = connection.State.ToString()
                    };
                }
                catch (Exception ex)
                {
                    oracleStats = new Dictionary<string, object>
                    {
                        ["Error"] = ex.Message,
                        ["IsHealthy"] = false
                    };
                }

                return Ok(new
                {
                    PoolStats = poolStats,
                    OracleStats = oracleStats,
                    Timestamp = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting Oracle pool status");
                return StatusCode(500, new { Error = ex.Message });
            }
        }

        /// <summary>
        /// 手动清理Oracle连接池
        /// </summary>
        [HttpPost("clear-oracle-pools")]
        [Authorize(Roles = "Admin,SystemAdmin")]
        public IActionResult ClearOraclePools()
        {
            try
            {
                OracleConnection.ClearAllPools();
                _logger.LogInformation("Oracle连接池已手动清理");
                
                return Ok(new
                {
                    Success = true,
                    Message = "Oracle连接池已清理",
                    Timestamp = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error clearing Oracle pools");
                return StatusCode(500, new { Error = ex.Message });
            }
        }

        /// <summary>
        /// 获取数据库连接池状态
        /// </summary>
        [HttpGet("database-pool-status")]
        public async Task<ActionResult<object>> GetDatabasePoolStatus()
        {
            try
            {
                var sqlServerStatus = await GetSqlServerPoolStatus();
                var oracleStatus = GetOraclePoolStatusInternal();
                
                return Ok(new 
                {
                    SqlServer = sqlServerStatus,
                    Oracle = oracleStatus,
                    Timestamp = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting database pool status");
                return StatusCode(500, new { Error = ex.Message });
            }
        }

        private async Task<object> GetSqlServerPoolStatus()
        {
            try
            {
                using var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection"));
                await connection.OpenAsync();
                
                var sql = @"
                    SELECT 
                        COUNT(*) as ActiveConnections,
                        @@MAX_CONNECTIONS as MaxConnections,
                        @@CONNECTIONS as TotalConnections
                ";
                
                var result = await connection.QuerySingleAsync<dynamic>(sql);
                return new 
                {
                    ActiveConnections = result.ActiveConnections,
                    MaxConnections = result.MaxConnections,
                    TotalConnections = result.TotalConnections,
                    ConnectionString = _configuration.GetConnectionString("DefaultConnection")?.Replace("Password=", "Password=***")
                };
            }
            catch (Exception ex)
            {
                return new { Error = ex.Message };
            }
        }

        private object GetOraclePoolStatusInternal()
        {
            try
            {
                var connectionString = _configuration.GetConnectionString("HisOracleConnection");
                var builder = new OracleConnectionStringBuilder(connectionString);
                
                return new 
                {
                    DataSource = builder.DataSource,
                    MinPoolSize = builder.MinPoolSize,
                    MaxPoolSize = builder.MaxPoolSize,
                    ConnectionTimeout = builder.ConnectionTimeout,
                    ConnectionLifeTime = builder.ContainsKey("Connection Lifetime") ? builder["Connection Lifetime"] : null,
                    Pooling = builder.Pooling,
                    ValidateConnection = builder.ContainsKey("Validate Connection") ? builder["Validate Connection"] : null
                };
            }
            catch (Exception ex)
            {
                return new { Error = ex.Message };
            }
        }
    }
}